import pygame
import time
import types
import random

### 可控制参数
screen_w=640
screen_h=550
N=10 # 地图宽度
block_w=50 # 每个单元格宽度

# 颜色
clr_bg=[255,255,255]
clr_map=[0,0,0]
clr_snake=[0,255,0]
clr_apple=[255,0,0]
clr_text=[0,0,255]

### 程序
pygame.init()
screen=pygame.display.set_mode([screen_w,screen_h])
screen.fill(clr_bg)


# 蛇的位置
c_r=(block_w-6)//2
c_x=block_w//2 # 在一个方框中，一个节点的中心坐标x
c_y=block_w//2 # 在一个方框中，一个节点的中心坐标y
snake=[[0,0]] # 每个节点的位置，0 是头
snake_footprint=[] # 足迹，用于绘制时的擦除
# 苹果的位置
apple=[1,0]

def isMatch(a,b):
    return a[0]==b[0] and a[1]==b[1]

def isMatchApple(next):
    return next[0]==apple[0] and next[1]==apple[1]

def isMatchSnake(next):
    global snake
    for a in snake:
        if isMatch(a,next):
            return True
    return False
def eatApple():
    snake.insert(0,apple)

def is_out_range(i,j):
    return i<0 or j<0 or i>=N or j>=N

# 绘制地图
def drawMap(N:int, block_w:int):
    i=0
    while i<=N:
        pygame.draw.line(screen,clr_map,(0,i*block_w),(N*block_w,i*block_w),1)
        pygame.draw.line(screen,clr_map,(i*block_w,0),(i*block_w,N*block_w),1)
        i+=1

# 蛇头画的稍大一点点
def drawSnake(snake):
    i=0
    for a in snake:
        i+=1
        r=c_r
        if i==1:
            r+=2
        pygame.draw.circle(screen, clr_snake, [a[0]*block_w+c_x,a[1]*block_w+c_y], r) # 一个节点
    # 擦除足迹
    global snake_footprint
    if len(snake_footprint)>1:
        a=snake_footprint
        pygame.draw.circle(screen, clr_bg, [a[0]*block_w+c_x,a[1]*block_w+c_y], c_r+2) # 一个节点
        snake_footprint=[]


def randApple():
    ss=[]
    i=0
    while i<N:
        j=0
        while j<N:
            #i,j
            if not isMatchSnake([i,j]):
                ss.append([i,j])
            j+=1
        i+=1
    # print(ss)
    return random.choice(ss)

def drawApple(apple):
    pygame.draw.circle(screen, clr_apple, [apple[0]*block_w+c_x,apple[1]*block_w+c_y], c_r) # 一个节点

def isWin():
    #蛇的长度达到了 N*N
    return len(snake) >= N*N

def drawFinish():
    s="Fail"
    if isWin():
        s="Win"
    font = pygame.font.Font(None, 100) 
    text = font.render(s, True, clr_text)
    # screen.blit(text, (screen.get_width() / 2 - text.get_width() / 2, screen.get_height() / 2 - text.get_height() / 2))  
    screen.blit(text, (block_w*N / 2 - text.get_width() / 2, block_w*N / 2 - text.get_height() / 2))  
    pygame.display.flip()


# 返回是否吃掉了apple
# 不允许回头
def snakeMove(dir:str)->bool:
    global snake
    global snake_footprint
    print(dir)
    head=snake[0]
    next=[head[0],head[1]] # 预期的下一个点
    if dir=="left":
        next[0]-=1
    if dir=="right":
        next[0]+=1
    if dir=="up":
        next[1]-=1
    if dir=="down":
        next[1]+=1
    print("next=",next)
    # 判断是否是回头
    if len(snake)>1:
        second=snake[1]
        if isMatch(next,second):
            #下一步是蛇的第二个节点，它在回头
            #禁止,啥都不做
            return False
    if is_out_range(next[0],next[1]):
        drawFinish()
        return False

    if isMatchApple(next):
        #碰到苹果
        eatApple()
        return True

    snake.insert(0,next)
    snake_footprint=snake.pop()
    return False


def start():
    drawMap(N,block_w)
    drawSnake(snake)
    apple=randApple()
    drawApple(apple)

    pygame.display.flip()

    running=True
    while running:
        for event in pygame.event.get():
            # print(event)
            if event.type == pygame.QUIT:
                running=False
            elif event.type == pygame.KEYDOWN:
                dir=""
                if event.key == pygame.K_UP:
                    dir="up"
                elif event.key == pygame.K_DOWN:
                    dir="down"
                elif event.key == pygame.K_LEFT:
                    dir="left"
                elif event.key == pygame.K_RIGHT:
                    dir="right"

                eated=snakeMove(dir)
                drawSnake(snake)
                if eated:
                    apple=randApple()
                    drawApple(apple)

                pygame.display.flip()

    pygame.quit()

def main():
   start() 


if __name__ == "__main__":
    main()